<?php
/**
 * Created by PhpStorm.
 * User: longli
 * VX: isa1589518286
 * Date: 2020/9/12
 * Time: 13:05
 * @link http://www.lmterp.cn
 */

namespace app\admin\controller\order;

use app\admin\controller\BaseController;
use app\common\library\Tools;
use app\common\model\Account;
use app\common\model\AccountPlatform;
use app\common\model\Channel;
use app\common\model\ChannelCarrier;
use app\common\model\OrdersReturn;
use app\common\model\SysCountries;
use app\common\model\Orders;
use app\common\model\OrdersDetail;
use app\common\model\Warehouse;
use app\common\service\logistics\ChannelService;
use app\common\service\orders\OrderService;
use app\common\service\platform\transform\AmazonOrder;
use Env;
use RuntimeException;
use think\Paginator;

class ManagerController extends BaseController
{
    /**
     * 显示订单列表
     * @return mixed
     */
    public function index()
    {
        if($this->request->isAjax())
        {
            $orders = $this->search();
            return apiResponsePage($orders);
        }
        $this->assign('platform', AccountPlatform::getAll());
        $this->assign('send_date', [0 => '今天', -1 => '昨天', -3 => '3天前', -6 => '7天前', -59 => '60天前']);
        $this->assign('sort', ['order_source_create_time' => '订单创建时间', 'total_price' => '订单价格', 'latest_delivery_time' => '剩余发货时间']);
        $this->assign('carrier', ChannelCarrier::getAll());
        $this->assign('select_order', [
            'order_no' => '平台订单号',
            'order_sn' => '内部订单号',
            'track_num' => '追踪号',
            'detail_sku' => '内部SKU',
            'detail_platform_sku' => '平台SKU',
            'spu' => 'SPU',
            'buyer_email' => '买家邮箱',
            'buyer_phone' => '买家电话',
            'buyer_mobile' => '买家手机',
        ]);
        // 允许修改的订单状态
        $this->assign('allow_order_status', [
            Orders::ORDER_LACK, Orders::ORDER_WAIT_PUR,
            Orders::ORDER_WAIT_PUR_ING, Orders::ORDER_WAIT_OUT,
            Orders::ORDER_RETURN, Orders::ORDER_RETURN_PART,
            Orders::ORDER_REJECT, Orders::ORDER_RISK,
            Orders::ORDER_FALSE, Orders::ORDER_CANCEL,
            Orders::ORDER_EXCEPTION, Orders::ORDER_PRICE_LOW,
            Orders::ORDER_SUCCESS,
        ]);

        // 允许修改的订单发货状态
        $this->assign('allow_order_send', [
            Orders::SEND_PART, Orders::SEND_WAIT_TIMEOUT, Orders::SEND_RETURN_ALL, Orders::SEND_RETURN_PART
        ]);
        $this->assign("print_status", Orders::$PRINT_STATUS);
        $this->assign("label_status", [0 => '未生成', 1 => '已生成']);
        $this->assign('account', Account::getAll());
        $this->assign('order_status', Orders::$ORDER_STATUS);
        $this->assign('send_status', Orders::$SEND_STATUS);
        $this->assign("select_channel", Channel::getAll());
        $country = SysCountries::getCodeNameCh();
        $this->assign('select_country', $country);
        $logistics = ChannelCarrier::field(['carrier_name', 'carrier_num', 'carrier_id'])
            ->where(['status' => ChannelCarrier::IS_YES])
            ->order("carrier_name")->select();
        $this->assign('select_logistics', $logistics);
        // 权限赋值
        $this->assign('is_show_export', $this->user->hasPermissions('/order/manager/export'));
        $this->assign('is_show_import', $this->user->hasPermissions('/order/manager/import'));
        $this->assign('is_show_platform_import', $this->user->hasPermissions('/order/manager/import_platform_order'));
        $this->assign('is_show_batch_print', $this->user->hasPermissions('/order/manager/batch_print'));
        $this->assign('is_show_delete', $this->user->hasPermissions('/order/manager/delete'));
        $this->assign('is_show_return', $this->user->hasPermissions('/order/manager/order_return'));
        $this->assign('is_show_declare', $this->user->hasPermissions('/order/manager/declare'));
        $this->assign('is_show_save', $this->user->hasPermissions('/order/manager/save'));
        $this->assign('is_show_invoice', $this->user->hasPermissions('/order/invoice/render'));
        $this->assign('is_show_black', $this->user->hasPermissions('/cus/black/push'));
        $this->assign('is_show_unlock', $this->user->hasPermissions('/order/manager/unlock'));
        $this->assign('is_show_lock', $this->user->hasPermissions('/order/manager/lock'));
        $this->assign('is_show_purchase', $this->user->hasPermissions('/order/manager/purchase'));
        $this->assign('is_show_repair', $this->user->hasPermissions('/order/manager/repair'));
        $this->assign('is_show_again', $this->user->hasPermissions('/order/manager/again'));
        return $this->fetch('index');
    }

     /**
     * 搜索订单
     * @return Paginator
     * @date 2020/09/02
     * @author longli
     */
    private function search()
    {
        $search = $this->request->get();
        $detail = ['product_code', 'item_id', 'sku', 'platform_sku', 'name', 'name_ch', 'attr', 'qty', 'return_qty', 'price', 'is_bundle', 'declare_en', 'declare_ch', 'customer_remark'];
        $orders = Orders::getTableFields();
        $custom = ['label_url', 'create_time'];
        // 验证是否有子查询
        $dwhere = $where = [];
        $where[] = ['warehouse_id', 'eq', $this->warehouse->warehouse_id]; // 添加默认仓库
        foreach($search as $k => $v)
        {
            if(in_array($k, $custom)) continue;
            if(in_array($k, $orders))
            {
                $where[] = [$k, "in", $v];
            }
            else if(Tools::startWith($k, 'detail_') && in_array(substr($k, strlen('detail_')), $detail))
            {
                $dwhere[substr($k, strlen('detail_'))] = $v;
            }
        }
        if(isset($search['send_date']))
            $where = array_merge($where, $this->parseScopeDateToWhere("shipping_time", $search['send_date']));

        $ordersModel = Orders::where($where)->with(['detail', 'account', 'currcode']);

        if(!empty($search['start_date']))
        {
            $ordersModel->where($this->parseLayuiRangeDate('order_source_create_time', $search['start_date']));
        }

        if(!empty($search['create_time']))
        {
            $ordersModel->where($this->parseLayuiRangeDate('create_time', $search['create_time']));
        }

        if(!empty($search['spu']))
        {
            $sku = \app\common\model\Product::getSkusBySpu(trim($search['spu']));
            $dwhere[] = ['sku', 'in', $sku];
        }

        if(isset($search['label_url']))
        {
            $ordersModel->where("label_url", $search['label_url']?"neq":"eq", "");
        }
        // 处理排序
        $sort = "order_id desc";
        if(!empty($search['sort']))
        {
            if($search['sort'] == 'latest_delivery_time')
            {
                $sort = "latest_delivery_time asc";
                $ordersModel->where("latest_delivery_time", ">=", date("Y-m-d"));
            }
            else
            {
                $sort = "{$search['sort']} desc";
            }
        }
        $ordersModel->order($sort);

        if(!empty($dwhere))
        {
            $ordersModel->where("order_id", "in", function($query)use($dwhere)
            {
                $query->table(OrdersDetail::getTable())->where($dwhere)->field("order_id");
            });
        }
        // 处理分页
        $limit = !empty($search['limit']) ? $search['limit'] : null;
        return $ordersModel->paginate($limit);
    }

    /**
     * 申报订单
     * @date 2021/03/10
     * @author longli
     */
    public function declare()
    {
        set_time_limit(0);
        $ids = $this->request->get("ids");
        if(empty($ids)) $this->error('非法操作');
        $out = \think\Console::call('declare', ["--ids={$ids}"])->fetch();
        !empty($out) ? $this->success('申报成功') : $this->error('申报失败');
    }

    /**
     * 退货订单
     * @date 2021/03/04
     * @author longli
     */
    public function order_return()
    {
        if($this->request->isPost())
        {
            $validate = \think\facade\Validate::make([
                'order_id'  => 'require',
                'in_id'  => 'require',
                //'channel_id'  => 'require',
                //'track_num'  => 'require',
                'logistics_price' => 'egt:0',
                'sku' => 'require|array',
                'return_qty' => 'require|array',
            ],[
                'order_id.require' => '非法操作',
                'in_id.require' => '收货仓库必选',
                //'channel_id.require' => '退货渠道必须',
                //'track_num.require' => '追踪号必填',
                'logistics_price.egt' => '运费不能小于0',
                'sku.require' => 'SKU 必填',
                'sku.array' => 'SKU 必须是数组',
                'return_qty.require' => '退货数量必填',
                'return_qty.array' => '退货数量必须是数组',
            ]);
            $retData = $this->request->post();
            if(!$validate->batch()->check($retData)) $this->error(join(', ', $validate->getError()));
            $info = [];
            $order = Orders::get($retData['order_id']);
            foreach($retData['sku'] as $k => $sku)
            {
                $qty = intval($retData['return_qty'][$k]);
                if($qty < 0)  $this->error("SKU【{$sku}】退货数量不能小于0");
                foreach($order->detail as $detail)
                {
                    if($detail->sku == $sku)
                    {
                        if($qty > $detail->qty)
                            $this->error("SKU【{$sku}】退货数量不能大于购买数量");
                        break;
                    }
                }
                $info[] = [
                    'sku' => $sku,
                    'qty' => $qty
                ];
            }

            $retData['return_info'] = $info;
            OrderService::getInstance()->addReturn($order, $retData);
            $this->success('添加退货成功');
        }
        $orderId = $this->request->get('order_id');
        if(empty($orderId)) $this->error('非法操作');
        if(!($order = Orders::get($orderId))) $this->error('订单不存在');
        if($returns = OrdersReturn::get(['order_id' => $order->order_id]))
            $this->assign('returns', $returns);
        $this->assign('warehouse', Warehouse::getAll());
        $this->assign('channel', Channel::getAll());
        $this->assign('currencies', SysCountries::getCurrencyAll());
        $this->assign('order', $order);
        return $this->fetch('returns_info');
    }

    /**
     * 退货订单
     * @date 2021/03/04
     * @author longli
     */
    public function returns()
    {
        if($this->request->isAjax())
        {
            $rets = $this->searchRets();
            $limit = $this->getPageSize();
            $rets = $rets->paginate($limit);
            $this->assign("list", $rets->getCollection());
            $this->assign("page", $rets->render());
            return $this->fetch('returns_lists');
        }
        $this->assign('channel', Channel::getAll());
        $this->assign('warehouse', Warehouse::getAll());
        $this->assign('account', Account::getAll());
        $this->assign('order_select', [
            'order_no' => '平台订单号',
            'track_num' => '追踪号',
            'order_sn' => '内部订单号',
        ]);
        return $this->fetch('returns');
    }

    /**
     * 查看订单退货详情
     * @date 2021/03/05
     * @author longli
     */
    public function return_track_info()
    {
        $rid = $this->request->get("rid");
        if(empty($rid)) $this->error("非法请求");
        $ret = OrdersReturn::get($rid);
        if(empty($ret)) $this->error("物流订单不存在");
        if(empty($ret->track_info)) $this->error("暂无物流信息");
        $trackInfo = json_decode($ret->track_info, true);
        $this->assign("trackInfo", $trackInfo);
        return $this->fetch("cha/order/track_info");
    }

    /**
     * 搜索退货订单
     * @date 2021/03/04
     * @author longli
     */
    private function searchRets()
    {
        $rets = OrdersReturn::with(['order.account', 'currcode']);
        $rets->where('in_id', $this->warehouse->warehouse_id);
        $this->searchModel($rets, [
            'eq' => ['out_id', 'track_num', 'channel_id'],
            'times' => ['send_time']
        ]);
        // 处理子查询
        $subSel = ['order_no', 'order_sn', 'account_id'];
        $rWhere = [];
        foreach($subSel as $f)
        {
            $text = $this->request->post($f, '', 'trim');
            if(empty($text) && !is_numeric($text)) continue;
            $rWhere[$f] = $text;
        }
        if(!empty($rWhere))
        {
            $rets->where("order_id", "IN", function($query)use($rWhere)
            {
                $query->table(Orders::getTable())->where($rWhere)->field("order_id");
            });
        }
        return $rets;
    }

    /**
     * 问题订单
     * @return string
     * @date 2020/09/02
     * @author longli
     */
    public function question()
    {
        $this->assign("other_filter", ['order_status' => Orders::ORDER_EXCEPTION]);
        return $this->index();
    }

    /**
     * 删除订单
     * @date 2020/09/02
     * @author longli
     */
    public function delete()
    {
        $ids = $this->request->get("ids");
        OrderService::getInstance()->deleteOrderById($ids)
            ? $this->success('删除成功')
            : $this->error('删除失败');
    }

    /**
     * 更新订单
     * @date 2020/09/02
     * @author longli
     */
    public function save()
    {
        $orderId = $this->request->request("order_id");
        if(empty($orderId)) $this->error('非法请求');
        $field = $this->request->post("field");
        $value = $this->request->post("value");
        if((is_array($field) && !is_array($value)) || (empty($field) || (empty($value) && !is_numeric($value))))
            $this->error('非法参数');
        if(is_array($field))
        {
            $data = [];
            foreach($field as $k => $f)
            {
                $data[$f] = $value[$k];
            }
        }
        else
        {
            $data = [$field => $value];
        }
        Orders::editByOrderId($orderId, $data)
            ? $this->success('更新成功')
            : $this->error('更新失败');
    }

    /**
     * 查看订单详情
     * @date 2020/09/03
     * @author longli
     */
    public function look()
    {
        if($this->request->isPost())
        {
            if(!Tools::isJson($this->request->getContent(), $data)) $this->error('非法请求');
            OrderService::getInstance()->addOrder($data)
                ? $this->success('订单保存成功')
                : $this->error('订单保存失败');
        }
        else
        {
            $orderId = $this->request->request("order_id");
            $order = Orders::with(['detail' => function($query){$query->hidden(['ext_json']);}])->get($orderId);
            $this->assign("order", $order);
            $this->assign("country", SysCountries::getCodeNameCh());
            $temp = array_flip(Orders::$ORDER_STATUS)[$order->order_status];
            $process = $temp == 0 ? 0 : round($temp / Orders::ORDER_SUCCESS * 100);
            $this->assign("process" , $process);
            return $this->fetch();
        }
    }

    /**
     * 导入订单
     * @date 2020/09/03
     * @author longli
     */
    public function import()
    {
        $file = $this->request->request("path");
        if(Tools::startWith($file, '/')) $file = Env::get("root_path") . "public{$file}";
        $orderImport = new \app\common\service\import\Order($file);
        try
        {
            $orderImport->run();
            return apiResponse(\app\common\status\BaseStatus::CODE_NORMAL, [], '导入成功');
        }catch(RuntimeException $e)
        {
            $this->error($e->getMessage());
        }
    }

    /**
     * 导入亚马逊平台表格订单
     * @date 2020/12/09
     * @author longli
     */
    public function import_platform_order()
    {
        $accountId = $this->request->post("account_id");
        $file = $this->request->post("path");
        $order = new AmazonOrder($accountId, Env::get("root_path") . "public{$file}");
        $msg = $order->read();
        if(!is_array($msg))
        {
            if(!$msg) $msg = "请检查表格是否从平台正常下载";
            $this->error("导入失败，$msg");
        }
        $order->push();
        $this->success('导入成功');
    }

    /**
     * 导出文件
     * @date 2020/09/03
     * @author longli
     */
    public function export()
    {
        $ids = $this->request->request("ids");
        $startDate = $this->request->request("start_date");
        if(empty($ids) && empty($startDate)) $this->error("非法导出，请检查导出条件");
        $condition = [];
        if(!empty($ids)) $condition[] = ['order_id', 'in', $ids];
        if(!empty($startDate)) $condition = array_merge($condition, $this->parseLayuiRangeDate('order_source_create_time', $startDate));
        $orderExport = new \app\common\service\export\Order();
        $file = $orderExport->runExcel($condition);
        $this->success("导出成功", '', ["src" => urlencode($file)]);
    }

    /**
     * 批量打印面单
     * @date 2020/09/03
     * @author longli
     */
    public function batch_print()
    {
        $ids = $this->request->get("ids");
        if(empty($ids)) $this->error("非法请求");
        $orders = Orders::field([
            'order_id', 'label_url', 'channel_id', 'is_print', 'order_status'
        ])->whereIn("order_id", $ids)->select();
        $chId = $label = [];
        foreach($orders as $order)
        {
            if(empty($order->label_url)) continue;
            $chId[] = $order->channel_id;
            $label[] = ChannelService::getInstance()->getLabelPath($order->label_url);
        }
        if(empty($label)) $this->error("未生成面单");
        $chId = array_unique($chId);
        $labelSize = array_values(ChannelService::getInstance()->getLabelSize($chId));
        if(count($chId) > 1)
        {
            for($i = 0; $i < count($labelSize) - 1; $i++)
            {
                if($labelSize[$i] != $labelSize[$i+1])
                    $this->error("所选择的面单尺寸不一样，请选择同一尺寸的面单");
            }
        }
        $size = array_values(current($labelSize));
        if(count($label) == 1)
        {
            $file = $label[0];
        }
        else
        {
            $path = config('temp_pdf') . "orders-label-" . date('YmdHis') . '-' . mt_rand(1000, 9999) . ".pdf";
            if(($file = ChannelService::getInstance()->mergePdf($label, $size, $path)) === false)
                $this->error("请联系管理员检查面单是否有异常");
        }
        foreach($orders as $order)
        {
            if(empty($order->label_url)) continue;
            // 更新面单打印状态
            $order->printLabel();
        }
        $byte = base64_encode(file_get_contents($file));
        $this->success('打印成功', '', ['file' => $byte]);
    }

    /**
     * 占用库存
     * @date 2021/04/05
     * @author longli
     */
    public function lock()
    {
        $ids = $this->request->get('ids');
        if(empty($ids)) $this->error("非法操作");
        $out = \think\Console::call('lock_stock', ['--action=order', "--type=lock", "--ids={$ids}"])->fetch();
        !empty($out)
            ? $this->success($out)
            : $this->error("占用库存失败");
    }

    /**
     * 释放库存
     * @date 2021/04/05
     * @author longli
     */
    public function unlock()
    {
        $ids = $this->request->get('ids');
        if(empty($ids)) $this->error("非法操作");
        $out = \think\Console::call('lock_stock', ['--action=order', "--type=unlock", "--ids={$ids}"])->fetch();
        !empty($out)
            ? $this->success($out)
            : $this->error("释放库存失败");
    }

    /**
     * 生成采购单
     * @date 2021/06/17
     * @author longli
     */
    public function purchase()
    {
        $ids = $this->request->get('ids');
        if(empty($ids)) $this->error('非法操作');
        $out = \think\Console::call('purchase', ['--action=generateByOrder', "--ids={$ids}"])->fetch();
        !empty($out)
            ? $this->success($out)
            : $this->error("生成失败");
    }

    /**
     * 修复订单产品映射关系
     * @date 2021/06/21
     * @author longli
     */
    public function repair()
    {
        $out = \think\Console::call('repairorder', ['sku', "--day=90"]);
        $this->success("订单修复成功");
    }

    /**
     * 再次发货
     * @date 2021/08/12
     * @author longli
     */
    public function again()
    {
        if($this->request->isAjax() && $this->request->isGet())
        {
            $orderId = $this->request->get("order_id");
            if(empty($orderId)) $this->error("非法操作");
            $order = Orders::get($orderId);
            if($order->isFBA() || $order->getData('send_status') < Orders::SEND_ALL)
                $this->error("订单不可再次发货");
            $this->assign('order', $order);
            // 渲染模板
            return $this->fetch('again');
        }
        $ids = $this->request->post("ids");
        $sku = $this->request->post("sku");
        $qty = $this->request->post("qty");
        if(empty($ids)) $this->error('非法操作');
        $orders = Orders::field(['order_id', 'track_num'])->where([
                ["order_id", "in", $ids],
                ["track_num", "neq", "FBA"],
                ["send_status", "egt", Orders::SEND_ALL]
            ])->select();
        if($orders->isEmpty()) $this->error("暂无再次发货的订单");
        $detail = [];
        if(!empty($qty))
        {
            $totalQty = 0;
            foreach($qty as $k => $q)
            {
                $totalQty += $q;
                $detail[] = [
                    'sku' => $sku[$k],
                    'qty' => $q,
                ];
                // 验证数量
                foreach($orders[0]->detail as $item)
                {
                    if($sku[$k] == $item->sku && $q > $item->qty)
                        $this->error("SKU【{$item->sku}】数量不能大于原订单数量");
                }
            }
            if($totalQty < 1) $this->error("发货数量不能小于1");
        }
        $service = OrderService::getInstance();
        foreach($orders as $order)
        {
            // 写入再次发货订单
            $service->againOrder($order->order_id, $detail);
        }
        $this->success("操作成功");
    }
}
